package com.luter.heimdall.samples.webflux.webfluxdemo.config;

import com.luter.heimdall.boot.webflux.filter.HeimdallAuthorizeFilter;
import com.luter.heimdall.core.authorization.authority.GrantedAuthority;
import com.luter.heimdall.core.authorization.store.AuthorizationStore;
import com.luter.heimdall.core.context.WebContextHolder;
import com.luter.heimdall.core.limiter.PasswordRetryLimiter;
import com.luter.heimdall.core.manager.AuthenticationManager;
import com.luter.heimdall.core.manager.AuthorizationManager;
import com.luter.heimdall.core.manager.HeimdallAuthenticationManager;
import com.luter.heimdall.core.manager.HeimdallAuthorizationManager;
import com.luter.heimdall.core.token.SimpleToken;
import com.luter.heimdall.plugins.aspectj.HeimdallAspectAnnotationHandler;
import com.luter.heimdall.plugins.jwt.processor.NimbusHMACJwtProcessor;
import com.luter.heimdall.plugins.redis.config.DefaultRedisTemplateConfiguration;
import com.luter.heimdall.plugins.redis.limiter.RedisPasswordRetryLimiter;
import com.luter.heimdall.plugins.redis.store.RedisAuthorizationStore;
import com.luter.heimdall.plugins.redis.store.RedisTokenStore;
import com.luter.heimdall.samples.webflux.webfluxdemo.service.SimulatorDataProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.List;
import java.util.Map;

/**
 * The type Auth config.
 *
 * @author luter
 */
@Configuration
public class HeimdallConfig extends DefaultRedisTemplateConfiguration {
    /**
     * 密码重试
     */
    @Autowired
    private StringRedisTemplate passwordRetryRedisTemplate;

    /**
     * 认证授权管理器
     *
     * @return the authorization manager
     */
    @Bean
    public AuthorizationManager authorizationManager(WebContextHolder webContextHolder,
                                                     RedisTemplate<String, Map<String, List<String>>> appAuthoritiesRedisTemplate,
                                                     RedisTemplate<String, List<? extends GrantedAuthority>> userAuthoritiesRedisTemplate,
                                                     RedisTemplate<String, SimpleToken> tokenRedisTemplate) {
        final AuthorizationStore authorizationStore =
                new RedisAuthorizationStore(appAuthoritiesRedisTemplate, userAuthoritiesRedisTemplate)
                        .dataProvider(new SimulatorDataProvider());
        final AuthenticationManager heimdallAuthenticationManager
                = new HeimdallAuthenticationManager(webContextHolder)
                //jwt 模式
                .jwtProcessor(new NimbusHMACJwtProcessor())
                //白名单支持
                .tokenStore(new RedisTokenStore(tokenRedisTemplate));
        return new HeimdallAuthorizationManager(authorizationStore, heimdallAuthenticationManager);
    }

    /**
     * 权限拦截器
     *
     * @param authorizationManager the authorization manager
     * @return the auth way authorize filter
     */
    @Bean
    public HeimdallAuthorizeFilter heimdallAuthorizeFilter(AuthorizationManager authorizationManager) {
        return new HeimdallAuthorizeFilter(authorizationManager);
    }

    /**
     * 注解授权
     *
     * @param authorizationManager the authorization manager
     * @return the Heimdall aspect annotation handler
     */
    @Bean
    public HeimdallAspectAnnotationHandler aspectHeimdallAnnotationHandler(AuthorizationManager authorizationManager) {
        return new HeimdallAspectAnnotationHandler(authorizationManager);
    }

    /**
     * 重试限制
     *
     * @return the password retry limiter
     */
    @Bean
    public PasswordRetryLimiter retryLimiter() {
        return new RedisPasswordRetryLimiter(passwordRetryRedisTemplate);
    }
}
